package org.irri.smta.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.Map;
import java.util.UUID;

import org.artofsolving.jodconverter.OfficeDocumentConverter;
import org.artofsolving.jodconverter.office.DefaultOfficeManagerConfiguration;
import org.artofsolving.jodconverter.office.OfficeManager;

public class ConverterUtils {
	
	public static String getContents(File targetFile) throws IOException {
		BufferedReader br = null;
		StringBuffer sb = new StringBuffer();
		try {
			br = new BufferedReader(new InputStreamReader(new FileInputStream(
					targetFile), "UTF-8"));
			String line;
			while ((line = br.readLine()) != null) {
				sb.append(line);
			}
			br.close();
		} catch (IOException e) {
			br.close();
			throw e;
		}
		return sb.toString();
	}
	
	/**
	 * Generates .rtf document from given template and the substitution data
	 * 
	 * @param templateName
	 *            Template data
	 * @param substitutionData
	 *            Hash map with the set of key-value pairs that represent
	 *            substitution data
	 * @return
	 */
	public static String generateRtf(Map<String, String> substitutionData, String templateDirectory,
			String templateFilename, String generatedDirectory) {

		String templateFilepath = templateDirectory + "/" + templateFilename;
		String randomFilename = UUID.randomUUID().toString();
		String targetFilename = generatedDirectory + "/" + randomFilename;

		try {
			File sourceFile = new File(templateFilepath);
			File targetFile = new File(targetFilename);
			copy(sourceFile, targetFile);
			changeData(targetFile, substitutionData);
			return targetFilename;
		} catch (IOException ioe) {
			System.out.println(ioe.getMessage());
			return null;
		}
	}

	/**
	 * Substitutes keys found in target file with corresponding data
	 * 
	 * @param targetFile
	 *            Target file
	 * @param substitutionData
	 *            Map of key-value pairs of data
	 * @throws IOException
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	private static void changeData(File targetFile,
			Map<String, String> substitutionData) throws IOException {

		String contents = getContents(targetFile);

		Iterator substitutionDataIterator = substitutionData.entrySet()
				.iterator();
		while (substitutionDataIterator.hasNext()) {
			Map.Entry<String, String> pair = (Map.Entry<String, String>) substitutionDataIterator
					.next();
			if (contents.contains(pair.getKey())) {
				if (pair.getValue() != null) {
					contents = contents.replace(pair.getKey(),
							pair.getValue());
				}
			}
		}

		FileOutputStream fos = null;
		try {
			fos = new FileOutputStream(targetFile);
			fos.write(contents.getBytes("UTF-8"));
			fos.close();
		} catch (IOException e) {
			fos.close();
			throw e;
		}
	}

	private static void copy(InputStream in, OutputStream out)
			throws IOException {

		byte[] buffer = new byte[1024];
		while (true) {
			int readCount = in.read(buffer);
			if (readCount < 0) {
				break;
			}
			out.write(buffer, 0, readCount);
		}
	}

	public static void copy(File file, OutputStream out) throws IOException {
		InputStream in = new FileInputStream(file);
		try {
			copy(in, out);
		} finally {
			in.close();
		}
	}

	public static void copy(InputStream in, File file) throws IOException {
		OutputStream out = new FileOutputStream(file);
		try {
			copy(in, out);
		} finally {
			out.close();
		}
	}

	public static void copy(File inputFile, File outputFile) throws IOException {
		InputStream in = new FileInputStream(inputFile);
		OutputStream out = new FileOutputStream(outputFile);
		try {
			copy(in, out);
		} finally {
			in.close();
			out.close();
		}
	}
	
	public static void delete(File targetFile) {
		if (targetFile.delete() && targetFile.exists()) {
			targetFile.delete();
		}
	}

	public static void convert(String officeDirectory, String inputFilepath,
			String outputDirectory, String outputFilename) throws Exception {
		OfficeManager officeManager = new DefaultOfficeManagerConfiguration()
				.setOfficeHome(officeDirectory).setPortNumber(8100)
				.setTaskExecutionTimeout(120000L).buildOfficeManager();
		officeManager.start();

		OfficeDocumentConverter converter = new OfficeDocumentConverter(
				officeManager);
		File inputFile = new File(inputFilepath);
		File outputFile = new File(outputDirectory + "/" + outputFilename);
		try {
			converter.convert(inputFile, outputFile);
		} catch (Exception e) {
			e.printStackTrace();
		}

		officeManager.stop();
	}

}
